Daily trade alerts for BTC

Mark Ziemann https://mdz-analytics.com

2022-09-29

Source code

Intro

In the backtesting analysis, I have established several different profitable strategies for timing entry/exits. Visit the BTC page to see how these signals were identified.

  1. Simple moving average (SMA)

  2. Exponential moving average (EMA)

  3. SMA crosses

  4. EMA crosses

  5. Directional movement index (DMI)

  6. True strength index (TSI) BEST

  7. Stochastic oscillator (stoch)

  8. Double RSI

  9. Donchian channel

  10. Know sure thing (KST)

  11. Ensembl indicator

This script will examine the price action and these trade signals just before the daily close. If the signal is TRUE, it is bullish and if FALSE it is bearish. When there is a switch from bearish to bullish it is a buy signal and when it switches from bullish to bearish it is a sell signal. This HTML is updated just before the daily close each day, but push notifications for any trade signals are also sent by push bullet.

To receive these signals in real-time, subscribe to the following channels - it’s free for a limited time!

https://www.pushbullet.com/channel?tag=btc_signal

If you need some help to design your own trading signals/strategies, I am happy to help for a fee. email me at mark.ziemann{αt}gmail.com for any enquiries/suggestions/feedback.

This report is distributed for FREE under the MIT licence, but if you find it useful, consider a small tip.

Monero Address

Reminder: this analysis is not financial advice.

suppressPackageStartupMessages({
  library("jsonlite")
  library("tidyverse")
  library("runner")
  library("quantmod")
  library("TTR")
  library("RPushbullet")
  library("kableExtra")
})

TESTING = FALSE

MYNOTE = NULL
mydate <- Sys.time()
attr(mydate, "tzone") <- "UTC"
mydate <- as.Date(mydate)

Get BTC parameters

params <- read.table("https://mdz-analytics.com/coins/BTC/BTC_dat.txt", header=TRUE)
params %>% kbl(caption="optimised backtested parameters") %>%  kable_styling("hover", full_width = F)
optimised backtested parameters
indicator parameter meanROI totalROI ntrades ndays xhodl
SMA 44 1.154362 914.2692 83 3404 5.853695
EMA 76 1.224865 633.1203 57 3404 4.053613
SMAcross 44,8 1.383369 1544.3129 37 3404 9.887610
EMAcross 56,26 2.856009 1574.6489 15 3404 10.081839
DMI 128 5.160312 948.1809 12 3404 6.070818
DC 21 1.326361 661.1740 37 3404 4.233229
TSI 100,4,15 1.132427 1261.2834 99 3404 8.075487
stoch 16,54,6 1.132085 729.6873 87 3404 4.671893
RSI2 57,95 1.129494 659.8321 103 3404 4.224638
KST 1.7,0.18,19 1.173615 1301.0709 83 3404 8.330230
Ensemble SMAcross,EMAcross,DMI,TSI,stoch,DC,KST,2 1.611814 2691.2032 51 3404 18.189243

Get BTC price data

Obtaining BTC price data (daily) for the last 300 days and today’s price.

URL="https://web-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical?symbol=BTC&convert=USD&interval=daily&count=300"
download.file(URL,destfile="btcdat.txt")
btcdat <- fromJSON("btcdat.txt")
price <- btcdat$data$quotes
price <- data.frame(  as.Date(price$time_close) , price$quote$USD$high, price$quote$USD$low, price$quote$USD$close)
colnames(price) <- c("date","high","low","close")

URL="https://web-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical?symbol=BTC&convert=USD&interval=hourly&time_period=hourly&count=11"
download.file(URL,destfile="btcdat.txt")
btcdat <- fromJSON("btcdat.txt")
price2 <- btcdat$data$quotes
price2 <- data.frame( as.Date(price2$time_close) , price2$quote$USD$high, price2$quote$USD$low, price2$quote$USD$close,stringsAsFactors=FALSE)
colnames(price2) <- c("date","high","low","close")

high <- max(price2[,2])
low <-  min(price2[,3])
close <- price2[nrow(price2),4]

df <- data.frame(date=mydate,high=high,low=low,close=close,stringsAsFactors=FALSE)
price <- rbind(price,df)
tail(price) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
date high low close
2022-09-24 19310.20 18861.97 18937.01
2022-09-25 19134.73 18696.47 18802.10
2022-09-26 19274.87 18721.29 19222.67
2022-09-27 20338.46 18915.67 19110.55
2022-09-28 19688.34 18553.30 19426.72
2022-09-29 19574.06 18924.35 19452.39
if ( TESTING == TRUE) {
  price[nrow(price),"Close"] <- price[nrow(price),"Close"] * 2
}

BTC SMA indicator

Now to determine whether BTC has crossed the SMA line.

price2 <- price

n <- as.numeric(params[params$indicator == "SMA",2])

price2$ma <- SMA(Cl(price2),n=n)
price2$signal <- price2$close > price2$ma
tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
date high low close ma signal
2022-09-24 19310.20 18861.97 18937.01 20814.90 FALSE
2022-09-25 19134.73 18696.47 18802.10 20687.61 FALSE
2022-09-26 19274.87 18721.29 19222.67 20569.40 FALSE
2022-09-27 20338.46 18915.67 19110.55 20451.01 FALSE
2022-09-28 19688.34 18553.30 19426.72 20343.96 FALSE
2022-09-29 19574.06 18924.35 19452.39 20243.26 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    btc_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    btc_signal="SELL"
  }
} else {
btc_signal <- "NONE"
}

if (today_signal==TRUE) {
  ens_SMA=TRUE
} else {
  ens_SMA=FALSE
}

message(paste("BTC SMA signal:",btc_signal))
## BTC SMA signal: NONE
plot(price2$close~as.Date(price2$date),type="l",
  xlab="Date",ylab="price (USD)",main="BTC w SMA")
grid()
lines(price2$ma~ as.Date(price2$date) ,col="red")

if ( btc_signal != "NONE") {
  MYNOTE <- paste("The BTC SMA signal is", btc_signal,".")
}

BTC EMA indicator

Now to determine whether BTC has crossed the EMA line.

price2 <- price

n <- as.numeric(params[params$indicator == "EMA",2])

price2$ma <- EMA(Cl(price2),n=n)
price2$signal <- price2$close > price2$ma
tail(price2) %>% kbl(row.names = FALSE) %>%  kable_styling("hover", full_width = F)
date high low close ma signal
2022-09-24 19310.20 18861.97 18937.01 21745.76 FALSE
2022-09-25 19134.73 18696.47 18802.10 21669.30 FALSE
2022-09-26 19274.87 18721.29 19222.67 21605.75 FALSE
2022-09-27 20338.46 18915.67 19110.55 21540.94 FALSE
2022-09-28 19688.34 18553.30 19426.72 21486.03 FALSE
2022-09-29 19574.06 18924.35 19452.39 21433.21 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    btc_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    btc_signal="SELL"
  }
} else {
  btc_signal <- "NONE"
}

if (today_signal==TRUE) {
  ens_EMA=TRUE
} else {
  ens_EMA=FALSE
}

message(paste("BTC EMA signal:",btc_signal))
## BTC EMA signal: NONE
plot(price2$close~as.Date(price2$date),type="l",
  xlab="Date",ylab="price (USD)",main="BTC EMA")
grid()
lines(price2$ma~ as.Date(price2$date) ,col="red")

if ( btc_signal != "NONE") {
  MYNOTE <- paste("The BTC EMA signal is", btc_signal,".")
}

BTC SMA cross indicator

The SMA cross is a reasonably good strategy.

price2 <- price

n <- as.numeric(unlist(strsplit(params[params$indicator == "SMAcross",2],",")))
n1 <- n[1]
n2 <- n[2]

price2$ma1 <- SMA(Cl(price2),n=n1)
price2$ma2 <- SMA(Cl(price2),n=n2)

price2$signal <- price2$ma2 > price2$ma1
tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
date high low close ma1 ma2 signal
2022-09-24 19310.20 18861.97 18937.01 20814.90 19272.20 FALSE
2022-09-25 19134.73 18696.47 18802.10 20687.61 19106.52 FALSE
2022-09-26 19274.87 18721.29 19222.67 20569.40 19081.91 FALSE
2022-09-27 20338.46 18915.67 19110.55 20451.01 19027.71 FALSE
2022-09-28 19688.34 18553.30 19426.72 20343.96 19094.70 FALSE
2022-09-29 19574.06 18924.35 19452.39 20243.26 19207.83 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    btc_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    btc_signal="SELL"
  }
} else {
btc_signal <- "NONE"
}

if (today_signal==TRUE) {
  ens_SMAcross=TRUE
} else {
  ens_SMAcross=FALSE
}

message(paste("BTC SMA cross signal:",btc_signal))
## BTC SMA cross signal: NONE
plot(price2$close~as.Date(price2$date),type="l",
  xlab="Date",ylab="price (USD)",main="BTC w SMA cross")
grid()
lines(price2$ma1~ as.Date(price2$date) ,col="red")
lines(price2$ma2~ as.Date(price2$date) ,col="blue")

if ( btc_signal != "NONE") {
  MYNOTE <- paste(MYNOTE, "The BTC SMA cross signal is", btc_signal,".")
}

BTC EMA cross indicator

The EMA cross is a moderately profitable strategy.

price2 <- price

n <- as.numeric(unlist(strsplit(params[params$indicator == "EMAcross",2],",")))
n1 <- n[1]
n2 <- n[2]

price2$ma1 <- EMA(Cl(price2),n=n1)
price2$ma2 <- EMA(Cl(price2),n=n2)

price2$signal <- price2$ma2 > price2$ma1
tail(price2) %>% kbl(row.names = FALSE) %>%  kable_styling("hover", full_width = F)
date high low close ma1 ma2 signal
2022-09-24 19310.20 18861.97 18937.01 20984.03 20031.22 FALSE
2022-09-25 19134.73 18696.47 18802.10 20907.47 19940.18 FALSE
2022-09-26 19274.87 18721.29 19222.67 20848.36 19887.03 FALSE
2022-09-27 20338.46 18915.67 19110.55 20787.38 19829.51 FALSE
2022-09-28 19688.34 18553.30 19426.72 20739.64 19799.68 FALSE
2022-09-29 19574.06 18924.35 19452.39 20694.47 19773.95 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    btc_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    btc_signal="SELL"
  }
} else {
  btc_signal <- "NONE"
}

if (today_signal==TRUE) {
  ens_EMAcross=TRUE
} else {
  ens_EMAcross=FALSE
}

message(paste("BTC EMA cross signal is",btc_signal))
## BTC EMA cross signal is NONE
plot(price2$close~as.Date(price2$date),type="l",
  xlab="Date",ylab="price (USD)",main="BTC EMA cross")
grid()
lines(price2$ma1~ as.Date(price2$date) ,col="red")
lines(price2$ma2~ as.Date(price2$date) ,col="blue")

if ( btc_signal != "NONE") {
  MYNOTE <- paste(MYNOTE, "The BTC EMA cross signal is", btc_signal,".")
}

BTC DMI indicator

Directional movement indicator is a good approach to identify trend changes.

n <- as.numeric(params[params$indicator == "DMI",2])

dmi.adx <- ADX(price[,c("high","low","close")],n=n)
price2 <- cbind(price,dmi.adx)
price2$signal <- dmi.adx[,1] > dmi.adx[,2]
tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
date high low close DIp DIn DX ADX signal
2022-09-24 19310.20 18861.97 18937.01 18.77333 27.24031 18.40103 17.89867 FALSE
2022-09-25 19134.73 18696.47 18802.10 18.72439 27.26775 18.57569 17.90396 FALSE
2022-09-26 19274.87 18721.29 19222.67 18.74619 27.17755 18.35949 17.90752 FALSE
2022-09-27 20338.46 18915.67 19110.55 19.22200 26.94666 16.73139 17.89833 FALSE
2022-09-28 19688.34 18553.30 19426.72 19.09159 26.98044 17.12286 17.89227 FALSE
2022-09-29 19574.06 18924.35 19452.39 19.01716 26.87525 17.12286 17.88626 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    btc_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    btc_signal="SELL"
  }
} else {
  btc_signal <- "NONE"
}

if (today_signal==TRUE) {
  ens_DMI=TRUE
} else {
  ens_DMI=FALSE
}

message(paste("BTC DMI signal:",btc_signal))
## BTC DMI signal: NONE
price2 <- as.data.frame(price2)
par(mfrow=c(2,1))
plot(price2$close~as.Date(price2$date),type="l",
  xlab="Date",ylab="price (USD)",main="BTC USD price")
grid()
plot(price2$DIp~as.Date(price2$date),type="l", col="blue",
  xlab="Date",ylab="price (USD)",main="BTC DMI")
grid()
lines(price2$DIn ~ as.Date(price2$date) ,col="red")

if ( btc_signal != "NONE") {
  MYNOTE <- paste(MYNOTE,"BTC DMI signal is", btc_signal,".")
}

BTC TSI indicator

True Strength Indicator is one of the more profitable approaches. Its success lies in how it changes rapidly when momentum shifts. For most coins, this indicator performs “best” in backtesting analysis, which means it should carry relatively more weight than other indicators.

n <- as.numeric(unlist(strsplit(params[params$indicator == "TSI",2],",")))
n1 <- n[1]
n2 <- n[2]
ns <- n[3]

TSI <- function(x, n.first = 25, n.second = 13, n.signal = 7) {
  #True Strength Indicator
  #https://school.stockcharts.com/doku.php?id=technical_indicators:true_strength_index
  x <- try.xts(x, error = as.matrix)
  pc <- x - lag.xts(x, na.pad = T) #force lag.xts to get na padding
  dspc <- EMA(EMA(pc, n = n.first), n = n.second)
  dsapc <- EMA(EMA(abs(pc), n = n.first), n = n.second)

  tsi <- 100 * (dspc/dsapc)
  signal <- EMA(tsi, n = n.signal)
  r <- cbind(tsi, signal)
  r <- reclass(r, x)
  if (!is.null(dim(r))) colnames(r) <- c("tsi", "signal")
  return(r)
}

tsi <- TSI(price$close , n.first = n1, n.second = n2, n.signal = ns )
colnames(tsi) <- c("tsi","sig")

price2 <- cbind(price,tsi)
price2$signal <- tsi[,1] > tsi[,2]
tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
date high low close tsi sig signal
2022-09-24 19310.20 18861.97 18937.01 -14.35621 -13.66366 FALSE
2022-09-25 19134.73 18696.47 18802.10 -14.66811 -13.78922 FALSE
2022-09-26 19274.87 18721.29 19222.67 -14.13987 -13.83305 FALSE
2022-09-27 20338.46 18915.67 19110.55 -13.96778 -13.84989 FALSE
2022-09-28 19688.34 18553.30 19426.72 -13.31960 -13.78360 TRUE
2022-09-29 19574.06 18924.35 19452.39 -12.88504 -13.67128 TRUE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    btc_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    btc_signal="SELL"
  }
} else {
  btc_signal <- "NONE"
}

if (today_signal==TRUE) {
  ens_TSI=TRUE
} else {
  ens_TSI=FALSE
}

message(paste("BTC TSI signal:",btc_signal))
## BTC TSI signal: NONE
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price")
grid()

plot(tsi[,1] ~ as.Date(price2$date),type="l",col="blue",
  xlab="Date",ylab="TSI",main="TSI")
lines(as.Date(price2$date), tsi[,2]  , col="red"  )
grid()

par(mfrow=c(1,1))
if ( btc_signal != "NONE") {
  MYNOTE <- paste(MYNOTE,"BTC TSI signal is", btc_signal,".")
}

BTC stochastic oscillator indicator

Similar to the TSI, the stoch can pinpoint early changes in momentum, however it may give many false positives.

n <- as.numeric(unlist(strsplit(params[params$indicator == "stoch",2],",")))
n1 <- n[1]
n2 <- n[2]
n3 <- n[3]

sto <- stoch(HLC(price), nFastK=n1 , nFastD=n2 , nSlowD=n2 , bounded = TRUE, smooth=n3)

price2 <- cbind(price,sto)
price2$signal <- price2$fastK > price2$fastD

tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
date high low close fastK fastD slowD signal
2022-09-24 19310.20 18861.97 18937.01 0.1796336 0.3831576 0.5048215 FALSE
2022-09-25 19134.73 18696.47 18802.10 0.1544441 0.3717256 0.5032955 FALSE
2022-09-26 19274.87 18721.29 19222.67 0.1702777 0.3618812 0.5015223 FALSE
2022-09-27 20338.46 18915.67 19110.55 0.1916893 0.3537722 0.4995370 FALSE
2022-09-28 19688.34 18553.30 19426.72 0.1921901 0.3460807 0.4973039 FALSE
2022-09-29 19574.06 18924.35 19452.39 0.2162139 0.3392218 0.4947980 FALSE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    btc_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    btc_signal="SELL"
  }
} else {
  btc_signal <- "NONE"
}

if (today_signal==TRUE) {
  ens_stoch=TRUE
} else {
  ens_stoch=FALSE
}

message(paste("BTC stoch signal:",btc_signal))
## BTC stoch signal: NONE
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price")
grid()

plot(price2$fastK ~ as.Date(price2$date),type="l",col="blue",
  xlab="Date",ylab="index",main="stochastic oscillator")
lines(as.Date(price2$date), price2$fastD  , col="red"  )
grid()

par(mfrow=c(1,1))
if ( btc_signal != "NONE") {
  MYNOTE <- paste(MYNOTE,"BTC Stoch signal is", btc_signal,".")
}

BTC double RSI indicator

Double RSI is simply two RSI lines.

n <- as.numeric(unlist(strsplit(params[params$indicator == "RSI2",2],",")))
n1 <- n[1]
n2 <- n[2]

rsi1 <- RSI(price$close,n=n1,maType=EMA)
rsi2 <- RSI(price$close,n=n2,maType=EMA)

price2 <- cbind(price,rsi1,rsi2)
price2$signal <- price2$rsi1 > price2$rsi2

tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
date high low close rsi1 rsi2 signal
2022-09-24 19310.20 18861.97 18937.01 42.36940 42.61492 FALSE
2022-09-25 19134.73 18696.47 18802.10 41.95434 42.38625 FALSE
2022-09-26 19274.87 18721.29 19222.67 43.73398 43.35395 TRUE
2022-09-27 20338.46 18915.67 19110.55 43.36684 43.15659 TRUE
2022-09-28 19688.34 18553.30 19426.72 44.72209 43.89217 TRUE
2022-09-29 19574.06 18924.35 19452.39 44.83309 43.95230 TRUE
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    btc_signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    btc_signal="SELL"
  }
} else {
  btc_signal <- "NONE"
}

if (today_signal==TRUE) {
  ens_RSI2=TRUE
} else {
  ens_RSI2=FALSE
}

message(paste("BTC RSI signal:",btc_signal))
## BTC RSI signal: NONE
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price")
grid()

plot(price2$rsi1 ~ as.Date(price2$date),type="l",col="blue",
  xlab="Date",ylab="index",main="double RSI")
lines(as.Date(price2$date), price2$rsi2  , col="red"  )
grid()

par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price")
grid()

plot(price2$rsi1/price2$rsi2 ~ as.Date(price2$date),type="l",
  xlab="Date",ylab="RSI ratio",main="double RSI")
grid()
abline(h=1,lty=2,lwd=2)

par(mfrow=c(1,1))
if ( btc_signal != "NONE") {
  MYNOTE <- paste(MYNOTE,"BTC RSI2 signal is", btc_signal,".")
}

BTC Donchian channel indicator

n <- as.numeric(params[params$indicator == "DC",2])

price2 <- price[1:nrow(price)-1,]
dc <- DonchianChannel(price2$close,n=n)

price2$higher <- c(NA,sapply(2:nrow(dc),function(i) {
  dc[i,"high"] > dc[(i-1),"high"]
} ))
price2$lower <- c(NA,sapply(2:nrow(dc),function(i) {
  dc[i,"low"] < dc[(i-1),"low"]
} ))
price2 <- price2[price2$higher != price2$lower,]
# show changing rows only
price2 <- price2[c(NA,unlist(lapply(2:nrow(price2) , function(i) {
  price2$higher[i] != price2$higher[i-1]
}))),]
price2 <- price2[!is.na(price2$higher),]

previous_signal <- price2[nrow(price2),"higher"]

price2 <- price
dc <- DonchianChannel(price2$close,n=n)
colnames(dc) <- c("dchigh","dcmid","dclow")
price2 <- cbind(price2,dc)

tail(price2) %>% kbl(row.names = FALSE) %>%  kable_styling("hover", full_width = F)
date high low close dchigh dcmid dclow
2022-09-24 19310.20 18861.97 18937.01 22370.45 20458.92 18547.4
2022-09-25 19134.73 18696.47 18802.10 22370.45 20458.92 18547.4
2022-09-26 19274.87 18721.29 19222.67 22370.45 20458.92 18547.4
2022-09-27 20338.46 18915.67 19110.55 22370.45 20458.92 18547.4
2022-09-28 19688.34 18553.30 19426.72 22370.45 20458.92 18547.4
2022-09-29 19574.06 18924.35 19452.39 22370.45 20458.92 18547.4
btc_signal="NONE"

# if we in negative territory, check whether time to buy
if ( previous_signal == FALSE ) {
  if ( price2[nrow(price2),"dchigh"] > price2[nrow(price2)-1,"dchigh"] ) {
    btc_signal="BUY"
  }
}

# if we in positive territory, check whether time to sell
if ( previous_signal == TRUE ) {
  if ( price2[nrow(price2),"dclow"] < price2[nrow(price2)-1,"dclow"] ) {
    btc_signal="SELL"
  }
}

if ( btc_signal=="NONE" ) {
  today_signal=previous_signal
} else {
  if (btc_signal=="BUY") { today_signal = TRUE }
  if (btc_signal=="SELL") { today_signal = FALSE }
}

if (today_signal==TRUE) {
  ens_DC=TRUE
} else {
  ens_DC=FALSE
}

message(paste("BTC DC signal:",btc_signal))
## BTC DC signal: NONE
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price",lwd=2)
grid()

lines(price2$dclow~ as.Date(price2$date),lwd=1.5,col="red")
lines(price2$dchigh~ as.Date(price2$date),lwd=1.5,col="limegreen")

price2 <- tail(price2,100)

plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price",lwd=2)
grid()

lines(price2$dclow~ as.Date(price2$date),lwd=1.5,col="red")
lines(price2$dcmid~ as.Date(price2$date),lwd=1.5,col="gray")
lines(price2$dchigh~ as.Date(price2$date),lwd=1.5,col="limegreen")

if ( btc_signal != "NONE") {
  MYNOTE <- paste(MYNOTE,"BTC Donchian channel signal is", btc_signal,".")
}

BTC KST indicator

Another high-performing indicator across different price series data.

price2 <- price

n <- as.numeric(unlist(strsplit(params[params$indicator == "KST",2],",")))
nScale <- n[1]
nrocScale <- n[2]
nSigs <- n[3]

kst <- KST(price2$close,n=nScale * c(10, 10, 10, 15) ,
  nROC=nrocScale * c(10, 15, 20, 30),
  nSig=nSigs)

price2 <- cbind(price2,kst)
price2$KST <- as.numeric(kst[,1]>kst[,2])

tail(price2) %>% kbl(row.names = FALSE) %>%  kable_styling("hover", full_width = F)
date high low close kst signal KST
2022-09-24 19310.20 18861.97 18937.01 -4.267549 -10.533729 1
2022-09-25 19134.73 18696.47 18802.10 -4.970936 -9.565604 1
2022-09-26 19274.87 18721.29 19222.67 -8.278076 -8.725006 1
2022-09-27 20338.46 18915.67 19110.55 -11.979918 -7.983860 0
2022-09-28 19688.34 18553.30 19426.72 -13.046608 -7.543171 0
2022-09-29 19574.06 18924.35 19452.39 -13.676157 -7.404482 0
today_signal <- price2[nrow(price2),"KST"]
previous_signal <- price2[(nrow(price2)-1),"KST"]
if (today_signal != previous_signal ) {
  if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
    signal="BUY"
  }
  if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
    signal="SELL"
  }
} else {
  signal <- "NONE"
}

if (today_signal==TRUE) {
  ens_DMI=TRUE
} else {
  ens_DMI=FALSE
}

message(paste("BTC KST signal:",btc_signal))
## BTC KST signal: NONE
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
  xlab="Date",ylab="price (USD)",main="USD price")
grid()

plot(kst[,1] ~ as.Date(price2$date),type="l",col="blue",
  xlab="Date",ylab="KST",main="KST")
lines(as.Date(price2$date), kst[,2]  , col="red"  )
grid()

par(mfrow=c(1,1))
if ( btc_signal != "NONE") {
  MYNOTE <- paste(MYNOTE,"BTC KST signal is", btc_signal,".")
}

BTC Ensemble indicator

This is a combination of a number of indicators.

ens <- params[params$indicator=="Ensemble","parameter"]
myrev <- intToUtf8(rev(utf8ToInt(ens)))
myrev <- unlist(strsplit(myrev,","))
# get thresh
n <- as.numeric(myrev[1])
myrev <- myrev[2:length(myrev)]
# get combination
combo <- sapply(myrev,function(s) { intToUtf8(rev(utf8ToInt(s))) })

message(paste("The combination is",paste(combo,collapse=" ")))
## The combination is KST DC stoch TSI DMI EMAcross SMAcross
message(paste("The buy threshold is",n))
## The buy threshold is 2
indicators <- c("SMA"=ens_SMA,
  "EMA"=ens_EMA,
  "SMAcross"=ens_SMAcross,
  "EMAcross"=ens_EMAcross,
  "DMI"=ens_DMI,
  "TSI"=ens_TSI,
  "stoch"=ens_stoch,
  "RSI2"=ens_RSI2,
  "DC"=ens_DC)

indicators <- indicators[names(indicators) %in% combo]
message("State of the indicators:")
## State of the indicators:
indicators
## SMAcross EMAcross      DMI      TSI    stoch       DC 
##    FALSE    FALSE    FALSE     TRUE    FALSE    FALSE
today_count <- sum(indicators)
message(paste("today_count_BTC",today_count,sep="="))
## today_count_BTC=1
today_signal <- today_count>=n

prev_html <- readLines("https://mdz-analytics.com/coins/BTC/alerts_BTC.html")
prev_signal <- length(grep("BTC ensemble indicator is BULLISH",prev_html))>2

btc_signal <- "NONE"

if ( today_signal != prev_signal ) {
  if ( today_signal == TRUE ) {
    btc_signal="BUY"
  } else {
    btc_signal="SELL"
  }
}

if (today_signal==TRUE) {
  message("BTC ensemble indicator is BULLISH")
} else {
  message("BTC ensemble indicator is BEARISH")
}
## BTC ensemble indicator is BEARISH
message(paste("BTC ENS signal:",btc_signal))
## BTC ENS signal: NONE
if ( btc_signal != "NONE") {
  MYNOTE <- paste(MYNOTE,"BTC Ensemble indicator is", btc_signal,".")
}

Send a push notification.

MYNOTE
## NULL
if ( !is.null(MYNOTE) ) {
  MYNOTE <- paste(MYNOTE, ". Visit https://mdz-analytics.com/coins/BTC/alerts_BTC.html for the details")
  MYNOTE
  pbPost("note", "Crypto Alert", MYNOTE ,channel="btc_signal")
}

Session information

For reproducibility


Click HERE to show session info

sessionInfo()
## R version 4.1.2 (2021-11-01)
## Platform: aarch64-unknown-linux-gnu (64-bit)
## Running under: Ubuntu 22.04.1 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/aarch64-linux-gnu/blas/libblas.so.3.10.0
## LAPACK: /usr/lib/aarch64-linux-gnu/lapack/liblapack.so.3.10.0
## 
## locale:
##  [1] LC_CTYPE=en_AU.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_AU.UTF-8        LC_COLLATE=en_AU.UTF-8    
##  [5] LC_MONETARY=en_AU.UTF-8    LC_MESSAGES=en_AU.UTF-8   
##  [7] LC_PAPER=en_AU.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_AU.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] kableExtra_1.3.4  RPushbullet_0.3.4 quantmod_0.4.20   TTR_0.24.3       
##  [5] xts_0.12.1        zoo_1.8-10        runner_0.4.1      forcats_0.5.1    
##  [9] stringr_1.4.0     dplyr_1.0.9       purrr_0.3.4       readr_2.1.2      
## [13] tidyr_1.2.0       tibble_3.1.8      ggplot2_3.3.6     tidyverse_1.3.2  
## [17] jsonlite_1.8.0   
## 
## loaded via a namespace (and not attached):
##  [1] httr_1.4.4          sass_0.4.2          viridisLite_0.4.0  
##  [4] modelr_0.1.8        bslib_0.4.0         assertthat_0.2.1   
##  [7] highr_0.9           googlesheets4_1.0.1 cellranger_1.1.0   
## [10] yaml_2.3.5          pillar_1.8.0        backports_1.4.1    
## [13] lattice_0.20-45     glue_1.6.2          digest_0.6.29      
## [16] rvest_1.0.2         colorspace_2.0-3    htmltools_0.5.3    
## [19] pkgconfig_2.0.3     broom_1.0.0         haven_2.5.0        
## [22] bookdown_0.28       scales_1.2.0        webshot_0.5.3      
## [25] svglite_2.1.0       tzdb_0.3.0          googledrive_2.0.0  
## [28] generics_0.1.3      ellipsis_0.3.2      cachem_1.0.6       
## [31] withr_2.5.0         cli_3.3.0           magrittr_2.0.3     
## [34] crayon_1.5.1        readxl_1.4.1        evaluate_0.16      
## [37] fs_1.5.2            fansi_1.0.3         xml2_1.3.3         
## [40] tools_4.1.2         hms_1.1.1           gargle_1.2.0       
## [43] lifecycle_1.0.1     munsell_0.5.0       reprex_2.0.2       
## [46] compiler_4.1.2      jquerylib_0.1.4     systemfonts_1.0.4  
## [49] rlang_1.0.4         grid_4.1.2          rstudioapi_0.13    
## [52] rmarkdown_2.15      gtable_0.3.0        DBI_1.1.3          
## [55] curl_4.3.2          R6_2.5.1            lubridate_1.8.0    
## [58] knitr_1.39          fastmap_1.1.0       utf8_1.2.2         
## [61] stringi_1.7.8       parallel_4.1.2      rmdformats_1.0.4   
## [64] Rcpp_1.0.9          vctrs_0.4.1         dbplyr_2.2.1       
## [67] tidyselect_1.1.2    xfun_0.32